<?php
/**
 * ResMania
 * More Information contact: info@resmania.com
 *
 * @package ResMania Install Controller
 * @version 0.5
 * @author webformatique
 * @copyright (C) 2010- webformatique
 * @license GNU/GPLv3 http://www.gnu.org/copyleft/gpl.html
 */

// no direct access
defined('_JEXEC') or die('Restricted access');

class ResMania_Install_Controller {

    /**
     * get all available versions
     */
    function getVersions($overrideVersion){
        $model = new ResMania_Install_Model();
        $versions = $model->getAllVersions();
        ob_clean();
        echo '{"stable":"'.$versions['stable'].'","beta":"'.$versions['beta'].'","selection":"'.$overrideVersion.'"}';
        die;
    }

    /*
      * Performs the checks and returns the results.
      *
      * return js array
    */
    function checks($JoomlaBase, $sid) {

        $model = new ResMania_Install_Model();

        $model->log("-------- installation started --------");

        session_name ($sid);
        @session_start(); // start or resume a session
        $_SESSION['count'] = null;
        if (!$model->log("Tracking ID:".$sid)) {
            $log = 0;
        } else {
            $log = 1;
        }

        $model->log("Installer Version: ".$model->getVersion());

        $model->log("Running PHP Check");
        $php = (int)$model->checkphp('5.2.5');

        $model->log("Running Folder Check");
        $folder = (int)$model->checkfolder($JoomlaBase); // 2 = ok, 0 = cant create, 1 = already exisit

        $model->log("Running DB Check");
        $innoDB = (int)$model->checkdb();
        $dbVersion = $model->getDBVersion();
        $model->log("DB Version: ".$dbVersion);

        $model->log("Checking Zend Framework");
        list($zend_framework, $zend_framework_version) = $model->checkzendframework();

        $model->log("Checking Optional PHP Directives");
        $phpDirectivesOptional = (int)$model->checkPHPdirectivesOptional();

        $model->log("Checking Required PHP Directives");
        $phpDirectivesRequired = (int)$model->checkPHPdirectivesRequired();

        $model->log("zlib support");
        $zlibSupport = (int)$model->checkZlib();

        // db drivers
        $pdoSupport = (int)$model->checkPDO();
        $mySQLiSupport = (int)$model->checkMySQLi();

        $model->log("PDO support: ".$pdoSupport);
        $model->log("MySQLi support: ".$mySQLiSupport);

        // check if we can read the destination size
        $destinSizeOK = (int)$model->checkDestinationSize(JURI::root(), $JoomlaBase);
        $model->log("Can read destination size: ".$destinSizeOK);

        // check if there is a core file already there...
        $corefileExists = (int)$model->checkCoreFileAlreadyExists(JURI::root());
        $model->log("core.zip detected: ".$corefileExists);

        $model->log("Checking Complete");

        ob_clean();
        echo '{"sid":"'.$sid.'", "log": '.$log.', "php":'.$php.',"folder":'.$folder.',"db":'.$innoDB.',"dbversion":"'.$dbVersion.'","zend_framework":'.$zend_framework.', "zend_framework_version":"'.$zend_framework_version.'", "phpdirectivesoptional":'.$phpDirectivesOptional.', "phpdirectivesrequired":'.$phpDirectivesRequired.', "pdosupport":'.$pdoSupport.',"mysqli":'.$mySQLiSupport.', "zlibsupport":'.$zlibSupport.',"destinsize":'.$destinSizeOK.',"corezipexists":'.$corefileExists.'}';
        die;
    }

    /*
      * This presents the download GUI
    */
    function download($sid, $overrideVersion, $licensekey, $noresume = "false") {

        // get the download path from the download server
        $model = new ResMania_Install_Model();

        if ($overrideVersion) $model->log("Version Override Detected!");
        $model->log("Download Started");

        $destination = JPATH_SITE.DS.'RM'.DS.'core.zip';

        // remove any old versions of core.zip
        if ($noresume == "true") {
            @unlink($destination);
        }

        // this is used to ensure the download and download progress use
        // the same session.
        @session_start(); // start or resume a session
        
        $source = $model->getDownloadSource();
        
        $model->log("Destination set as: ".$destination);

        $copyResult = false;
        $desinationSize = 0;

        // try to use fopen first...
        if ($copyResult = $model->fileDownload($source, $destination)){
            $model->log("Used PHP fopen function to download core from distribution point");
        } elseif (@function_exists('copy')) { // if fopen fails then try copy...
            $model->log("Used PHP Copy function to download core from distribution point");
            $copyResult = @copy($source, $destination);
        }

        if ($copyResult) {
            $copyResultMsg="Ok";
        }else {
            $copyResultMsg="Failed";
        }
        $model->log("Copy Result: ".$copyResultMsg);

        $sourceSize = (float)$_SESSION['sourceFileSize'];
        $desinationSize = (float)@filesize($destination);
        if (!$desinationSize) {
            // if filesize fails try using the getRemoteSize method
            $destinationfileURL = JURI::root()."RM/core.zip";
            $destinationSize = $model->getRemoteFileSize($destinationfileURL);
        }

        ob_clean();
        if ($copyResult || ($sourceSize == $desinationSize)) {
            echo '{"success": true, "error": "copy completed ok"}';
        } else {
            echo '{"success": false, "error": "System cannot copy Resmania core file:<a href='.$source.'>'.$source.'</a> to RM directory: '.JPATH_SITE.DS.'RM'.DS.' . This maybe because your server has blocked in-bound connections. First check with your provider that your server can download files from: '.$this->_disto_point.'"}';
        }
        die;
    }

    /*
     * Unzip the core
    */
    function unzipCore() {

        $model = new ResMania_Install_Model();

        $model->log("Unzip Started");

        $source = JPATH_SITE.DS.'RM'.DS.'core.zip';
        $unzipDestination = JPATH_SITE.DS.'RM';

        $model->removeNonBaseExtensions($unzipDestination);

        $model->log("Unzip Destination: ".$unzipDestination);

        if (file_exists($unzipDestination)) {
            $model->log("/RM folder already exists");
            $folderCreateResult = true;
        } else {
            $folderCreateResult = mkdir($unzipDestination);
            $model->log("Folder Creation Result".$folderCreateResult);
        }

        if (!$folderCreateResult) {
            ob_clean();
            echo '{"success": 0, "error": "System cannot create a folder:'.$unzipDestination.' for Resmania core. This maybe bacause the RM folder does not have the correct permissions or owner."}';
            die;
        }

        $model->log("Unzip Started");

        //$unzipResult = JArchive::extract($destination, $unzipDestination);
        $unzipResult = $model->unpackZip($source, $unzipDestination);

        $model->log("Unzip Result: ".$unzipResult);

        ob_clean();
        if (!$unzipResult) {
            //TODO: add translation
            echo '{"success": 0, "error": "System cannot unzip:'.$source.' to '.$unzipDestination. ' . This maybe because your system does not have the zlib libaraies installed that allow handling of ZIP files. You should check PHPinfo for zlib"}';
            die;
        }

        echo '{"success": 1,"error":""}';
        die;
    }

    /*
      * Get the percentage of the file downloaded.
      */
    function downloadProgress($sid) {

        $model = new ResMania_Install_Model();

        @session_start($sid); // start or resume a session

        $destinationfileURL = JURI::root()."RM/core.zip";
        $destinationSize = $model->getRemoteFileSize($destinationfileURL);
        $sourceSize = $model->getSourceSize($sid);

        if ($sourceSize>0 && $destinationSize>0) {
            $progress = round((100/$sourceSize) * $destinationSize,0);
        } else {
            $progress = 0;
        }

        $model->log("Download Progress: source size:".$sourceSize." destination size:".$destinationSize." (".$progress."%) Tracking ID:".$sid);

        // count starts when the JS code and the progress reach 100% after 4 calls of
        // this method ~20 seconds the count condition will be met and the ajax will
        // be sent a signal to continue to the next process. note: this is a nominal
        // value $count<10 the comparison is dealt with in the JS code
        $count = 0;
        if (isset($_SESSION['count'])) {
            $count = (int)$_SESSION['count'];
        }

        if ($progress == 100 && $count<10) {
            $count = $count + 1;
            $_SESSION['count'] = $count;
        }

        ob_clean();
        echo '{"progress":'.$progress.',"count": '.$count.'}';
        die;

    }

    /**
     * Scan folder and returns all filenames
     *
     * @param string $folder path to folder
     * @param array $allowedExtensions this is an array containing allowable filetypes if null filter will not be applied, this should be a list of extensions as a strings in lowercase
     * @return array - list of all file names, except .svn files
     */
    function getFiles($folder, $allowedExtensions = null)
    {
        $files = array();
        if (is_dir($folder) == false) return $files;

        if ($handle = opendir($folder)) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != ".." && $file != ".svn") {
                    if ($allowedExtensions == null) {
                        $files[] = $file;
                    } else {
                        $chunks = explode('.', $file);
                        $extension = strtolower($chunks[count($chunks) - 1]);
                        if (in_array($extension, $allowedExtensions)) {
                            $files[] = $file;
                        }
                    }
                }
            }
        }
        closedir($handle);
        return $files;
    }

    /*
      * This completes the DB installation
      */
    function setupDB()
    {
        $model = new ResMania_Install_Model();
        $model->log("Database Setup Started");

        $basePath = JPATH_SITE.DS.'RM'.DS;

        $newDB = false;
        if (isset($_REQUEST['new'])) {
            $newDB = (bool)$_REQUEST['new'];
        }
        $isUpgrade = !$newDB;

        $fileContents = array();
        if ($newDB) {
            // new DB installation
            $model->log("New DB Option Selected");
            $sqlFile = $basePath.'system'.DS.'sql'.DS.'install.sql';
            $fileContents[] = file_get_contents($sqlFile);
        } else {
            // Upgrade the DB
            $model->log("Upgrade DB Option Selected");

            $dbVersion = $model->getDBVersion();
            $model->log("Current Database Version: ".$dbVersion);

            $version = $model->getLatestVersion();
            $model->log("New Database Version: ".$version);

            // if we are already at the latest revision exit
            if ($dbVersion == $version) {
                $model->log("No DB Upgrade Action Required as DB Version is at Latest Revision");
                ob_clean();
                echo '{"success": 1,"error":""}';
                die;
            }

            // Remove all dots from version so we will get the integer of the version. ie: 1211630
            $dbCurrentVersionNumber = (int)str_replace(".","", $dbVersion);

            $sqlPath= implode(DS, array(
                $basePath,
                'system',
                'sql'
            ));

            $filesContent = array();
            $files = $this->getFiles($sqlPath, array('sql'));
            $numbers = array();
            foreach ($files as $file) {
                $chunks = explode('.', $file);
                if (count($chunks) == 3 && $chunks[1] == 'upgrade') {
                    $numbers[] = $chunks[0];
                }
            }
            sort($numbers);
            foreach ($numbers as $number) {
                if ($number > $dbCurrentVersionNumber) {
                    $sqlFile = $sqlPath.DS.$number.".upgrade.sql";
                    if (file_exists($sqlFile)) {
                        $filesContent[] = file_get_contents($sqlFile);
                        $model->log("SQL Uprade to be applied: ".$sqlFile);
                    }
                }
            }
        }

        foreach ($fileContents as $fileContent) {
            $result = $model->parseSQL($fileContent, $isUpgrade, $this->_getQueriesCount());
            if (!$result) {
                ob_clean();
                echo '{"success": 0,"error":"(123) The database query for installation/upgrade has failed!"}';
                die;
            }
        }
        $model->log("DB installation/upgrade done successfully.");

        // is we get this far return success
        ob_clean();
        echo '{"success": 1,"error":""}';
        die;
    }

    /**
     * Returns how many queries are in downloaded core to setup.
     *
     * @return int
     */
    protected function _getQueriesCount()
    {
        $configFilepath = JPATH_SITE.DS.'RM'.DS.'system'.DS.'config'.DS.'core.config.ini';
        $config = @parse_ini_file($configFilepath, true);
        if (!$config) {
            return null;
        }
        if (isset($config['main']['queries']) == false) {
            return null;
        }
        return $config['main']['queries'];
    }

    /*
     * this function does a quick installation check
     *
     */
    function postCheck() {

        $model = new ResMania_Install_Model();

        // 1. check the correct folders are writable within the RM folder
        $basePath = JPATH_SITE.DS.'RM'.DS;

        // all writable folders...
        $writeableFolders = array(
            $basePath.'userdata'.DS.'temp',
            $basePath.'userdata'.DS.'images'.DS.'media',
            $basePath.'userdata'.DS.'images'.DS.'units',
            $basePath.'userdata'.DS.'logs',
            $basePath.'userdata'.DS.'languages',
            $basePath.'userdata'.DS.'backups',
            $basePath.'userdata'.DS.'modules',
            $basePath.'userdata'.DS.'plugins'
        );

        // now loop through each folder and check if they are writable
        $folderCheck = true;
        foreach ($writeableFolders as $folder) {
            if (!is_writable($folder)) {
                $folderCheck = false;
            }
        }

        // 2. check the table structure is correct and healthy

        // open the db check list...
        $db =& JFactory::getDBO();
        $lines = file(JPATH_SITE.DS."administrator".DS."components".DS."com_resmania".DS."installation".DS."test".DS."db_check.txt");

        $dbCheck = true;
        foreach ($lines as $line) {
            $db->setQuery("SHOW TABLES LIKE '".trim($line)."'");
            $result = $db->loadAssoc();
            if (!empty($result)) {
                foreach ($result as $r) {
                    if (trim($r)!=trim($line))$dbCheck = false;
                }
            }
        }

        // 3. remove the core.zip file
        $corefile = JPATH_SITE.DS."RM".DS."core.zip";
        if (file_exists($corefile)){
            unlink($corefile);
        }

        ob_clean();
        echo '{"folderCheck":'.$folderCheck.',"dbCheck":'.$dbCheck.'}';
        die;
    }
}
?>
